package com.qianyitian.hope2.analyzer.model;

import com.qianyitian.hope2.analyzer.util.Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by bing.a.qian on 10/2/2017.
 */
public class FixInvestmentAccount {
    public static final int SAME_COST_EVERY_DAY = 1;
    public static final int SAME_COST_EVERY_WEEK = 5;
    public static final int SAME_COST_EVERY_MONTH = 20;

    int days2NowNumber;
    double amount;
    double cost;

    public FixInvestmentAccount(int days2NowNumber) {
        this.days2NowNumber = days2NowNumber;
    }


    public void run(List<Number[]> bars, int type) {
        if (type == SAME_COST_EVERY_DAY || type == SAME_COST_EVERY_WEEK || type == SAME_COST_EVERY_MONTH) {
            runSameCost(bars, type);
        } else {
            throw new RuntimeException("type error in FixInvestmentAccount");
        }
    }

    // it is useless of same amount buying in investment practice.
//    private void runSameAmount(List<Number[]> bars) {
//        double ONE_BUY_Amount = 1;
//        int barCount = bars.size();
//        int limit = Math.min(days2NowNumber, barCount);
//        List<ProfitDaily> dailyProfit = new ArrayList<>();
//        for (int i = barCount - limit; i < barCount; i++) {
//            Number[] oneBar = bars.get(i);
//            ProfitDaily profitDaily = new ProfitDaily();
//            profitDaily.setDate(oneBar[0].longValue());
//            dailyProfit.add(profitDaily);
//            amount = amount + ONE_BUY_Amount;
//            cost = cost + ONE_BUY_Amount * oneBar[4].doubleValue();
//
//            if (cost > 0) {
//                profitDaily.profit = amount * oneBar[4].doubleValue() / cost - 1;
//            } else {
//                profitDaily.profit = 0;
//            }
//        }
//        setProfits(convert2ChartFormat(dailyProfit));
//    }

    private void runSameCost(List<Number[]> bars, int type) {
        double ONE_BUY_CASH = 1;
        int barCount = bars.size();
        int limit = Math.min(days2NowNumber, barCount);
        List<ProfitDaily> dailyProfit = new ArrayList<>();
        for (int i = barCount - limit; i < barCount; i++) {
            Number[] oneBar = bars.get(i);
            ProfitDaily profitDaily = new ProfitDaily();
            profitDaily.setDate(oneBar[0].longValue());
            dailyProfit.add(profitDaily);

            if (i % type == 0) {
                cost = cost + ONE_BUY_CASH;
                amount = amount + (ONE_BUY_CASH / oneBar[4].doubleValue());
            }
            if (cost > 0) {
                profitDaily.profit = amount * oneBar[4].doubleValue() / cost - 1;
            } else {
                profitDaily.profit = 0;
            }
        }
        setProfits(convert2ChartFormat(dailyProfit));
    }

    public void run(List<Number[]> bars, List<Long> buyDateList) {
        double ONE_BUY_CASH = 1;
        int barCount = bars.size();

        int limit = Math.min(days2NowNumber, barCount);
        List<ProfitDaily> dailyProfit = new ArrayList<>();
        for (int i = barCount - limit; i < barCount; i++) {
            Number[] oneBar = bars.get(i);
            ProfitDaily profitDaily = new ProfitDaily();
            profitDaily.setDate(oneBar[0].longValue());
            dailyProfit.add(profitDaily);
            long dateLong = oneBar[0].longValue();
            if (buy(dateLong, buyDateList)) {
                cost = cost + ONE_BUY_CASH;
                amount = amount + (ONE_BUY_CASH / oneBar[4].doubleValue());
            }
            if (cost > 0) {
                profitDaily.profit = amount * oneBar[4].doubleValue() / cost - 1;
            } else {
                profitDaily.profit = 0;
            }
        }
        //平均持股成本价
        setProfits(convert2ChartFormat(dailyProfit));
    }

    private boolean buy(long dateLong, List<Long> buyDateList) {
        for (Long buyDateLong : buyDateList) {
            if (buyDateLong == dateLong) {
                return true;
            }
        }
        return false;
    }

    protected List<Number[]> convert2ChartFormat(List<ProfitDaily> dailyProfit) {
        List<Number[]> collect = dailyProfit.stream().map(bar -> {
            Number[] row = new Number[]{bar.getDate(), bar.getProfit() * 100};
            return row;
        }).collect(Collectors.toList());
        return collect;
    }


    List<Number[]> profits = null;


    public List<Number[]> getProfits() {
        return profits;
    }

    public void setProfits(List<Number[]> profits) {
        this.profits = profits;
    }

    public double getAmount() {
        return amount;
    }

    public double getCost() {
        return cost;
    }

    public Profit getProfit() {
        Profit profit = new Profit();
        profit.setAverageCostPrice(Utils.get2Double(getCost() / getAmount()));
        profit.setProfits(getProfits());
        return profit;
    }
}


